/**
 * Created by hukekuan on 2017/12/20.
 */

//构造函数
function C3GIS(options) {
    this.options = options;
    // 添加弹窗div
    var mapDiv = document.getElementById("map"),
        popupDiv = document.createElement("div");
    popupDiv.setAttribute("id", "popup");
    popupDiv.setAttribute("class", "ol-popup");
    mapDiv.parentNode.insertBefore(popupDiv,mapDiv);

    // 地图初始化
    this.mapInit();
}

//标记矢量图层的移动和单击事件
C3GIS.prototype.interactionSelect = {pointerMove:null, click:null}
C3GIS.prototype.popupOverlay = null

/**********************************map start*****************************************/
/**
 * 地图初始化
 */
C3GIS.prototype.mapInit = function (options) {
    var _this = this;
    _this.popupOverlay = new ol.Overlay({
        id:"popup",
        autoPan: true,
        autoPanAnimation: {
            duration: 250
        }
    });
    _this.mainMap = new ol.Map({
        target: _this.options.target,
        controls: ol.control.defaults({zoom: false, attribution: false}).extend([]),
        view: new ol.View({
            center: _this.options.center,
            zoom: _this.options.zoom,
            minZoom: _this.options.minZoom,
            maxZoom: _this.options.maxZoom,
            projection: _this.options.projection
        }),
        logo:false,
        overlays: [_this.popupOverlay]
    });
}

C3GIS.prototype.zoomMapByPolygon = function (polygon) {
    this.mainMap.getView().fit(polygon,{constrainResolution: false});
}

/**********************************map start*****************************************/

/**
 * 根据名称获取Interaction
 * @param interactionName
 * @returns {*}
 */
C3GIS.prototype.getInteractionByName = function (interactionName) {
    var _this = this, resultInteraction = null, interactionProperties,
        interactionArray = _this.mainMap.getInteractions().getArray();
    if(interactionArray.length == 0){
        return resultInteraction;
    }
    for(var i = 0,len = interactionArray.length;i < len;i++){
        interactionProperties = interactionArray[i].getProperties();
        if(interactionProperties != null
            && interactionProperties.hasOwnProperty("name")
            && interactionProperties["name"] == interactionName){
            resultInteraction = interactionArray[i];
            break;
        }
    }
    return resultInteraction;
}

/**
 * 向地图中为图层添加interaction，如果已经存在，先删除再添加
 * @param layerName
 * @param interactionType,（pointerMove、click）
 * @param interactionStyle, interaction触发样式
 * @param interactionCallback, interaction触发函数
 */
C3GIS.prototype.addInteraction = function (layerName,interactionType,interactionStyle,interactionCallback) {
    var _this = this,
        selectedLayer = _this.getLayByName(layerName);

    if(selectedLayer != null){
        if(interactionType == "pointerMove"){
            if(_this.interactionSelect.pointerMove != null){
                _this.mainMap.removeInteraction(_this.interactionSelect.pointerMove);
            }
            _this.interactionSelect.pointerMove = new ol.interaction.Select({
                wrapX: false,
                condition: ol.events.condition.pointerMove,
                layers: [selectedLayer],
                style: interactionStyle == null ?function(feature){
                    return null;
                } : interactionStyle
            });
            _this.mainMap.addInteraction(_this.interactionSelect.pointerMove);
        }else if(interactionType == "click"){
            if(_this.interactionSelect.click != null){
                _this.mainMap.removeInteraction(_this.interactionSelect.click);
            }

            _this.interactionSelect.click = new ol.interaction.Select({
                wrapX: false,
                condition: ol.events.condition.click,
                layers: [selectedLayer],
                style: interactionStyle == null ?function(feature){
                    return null;
                }: interactionStyle
            });
            _this.interactionSelect.click.on("select",interactionCallback == null ? function(e){}:interactionCallback);
            _this.mainMap.addInteraction(_this.interactionSelect.click);
        }
    }
}

/**
 * 删除矢量图层的悬浮和单击事件
 */
C3GIS.prototype.removeAllSelectInteraction = function () {
    var _this = this;
    if(_this.interactionSelect.pointerMove != null){
        _this.mainMap.removeInteraction(_this.interactionSelect.pointerMove);
        _this.interactionSelect.pointerMove = null;
    }

    if(_this.interactionSelect.click != null){
        _this.mainMap.removeInteraction(_this.interactionSelect.click);
        _this.interactionSelect.click = null;
    }
}

/**
 * 删除指定名称的interaction
 * @param interactionName
 */
C3GIS.prototype.removeInteraction = function (interactionName) {
    var _this = this, selectInteraction =_this.getInteractionByName(interactionName);
    if(selectInteraction != null){
        _this.mainMap.removeInteraction(selectInteraction);
    }
}


/**********************************layer start*****************************************/
/**
 * 根据图层编号获取图层
 */
C3GIS.prototype.getLayerById = function (layerId) {
    var _this = this,
        resultLayer = null,
        layerProperties,
        layerArray = _this.mainMap.getLayers().getArray();
    if(layerArray.length == 0){
        return resultLayer;
    }
    for(var i = 0,len = layerArray.length;i < len;i++){
        layerProperties = layerArray[i].getProperties();
        if(layerProperties != null
            && layerProperties.hasOwnProperty('layerId')
            && layerProperties['layerId'] == layerId){
            resultLayer = layerArray[i];
            break;
        }
    }
    return resultLayer;
}

/**
 * 根据图层名获取图层
 * @param layerName
 * @returns {*}
 */
C3GIS.prototype.getLayByName = function (layerName) {
    var _this = this,
        resultLayer = null,
        layerProperties,
        layerArray = _this.mainMap.getLayers().getArray();
    if(layerArray.length == 0){
        return resultLayer;
    }
    for(var i = 0,len = layerArray.length;i < len;i++){
        layerProperties = layerArray[i].getProperties();
        if(layerProperties != null
            && layerProperties.hasOwnProperty('name')
            && layerProperties['name'] == layerName){
            resultLayer = layerArray[i];
            break;
        }
    }
    return resultLayer;
}

/**
 * 根据配置信息生成图层并添加到地图中
 * @param layerType
 * @param layerName
 * @param layerOptions
 */
C3GIS.prototype.addLayer = function (layerType,layerName,layerOptions) {
    var _this = this,
        layer = null,
        layerProperty = {name:layerName},
        pointerMove,click;

    if(layerType == null || layerType == "") return;

    //图层初始属性添加

    if(layerOptions.hasOwnProperty("extent")
        && layerOptions['extent'] != null
        && layerOptions['extent'].length == 4){
        layerProperty['extent'] = layerOptions.extent
    }
    if(layerOptions.hasOwnProperty("maxResolution") && layerOptions['maxResolution'] != null){
        layerProperty['maxResolution'] = layerOptions.maxResolution
    }
    if(layerOptions.hasOwnProperty("minResolution") && layerOptions['minResolution'] != null){
        layerProperty['minResolution'] = layerOptions.minResolution
    }
    if(layerOptions.hasOwnProperty("opacity") && layerOptions['opacity'] != null){
        layerProperty['opacity'] = layerOptions.opacity
    }
    if(layerOptions.hasOwnProperty("visible") && layerOptions['visible'] != null){
        layerProperty['visible'] = layerOptions.visible
    }

    switch(layerType){
        case "ol.layer.Group":
            if(layerOptions.hasOwnProperty("layers")
                && Object.prototype.toString.call(layerOptions.layers) == "[object Array]"){
                layer = new ol.layer.Group({
                    layers:layerOptions.layers
                });
            }
            break;
        case "ol.layer.Tile":
            layer = new ol.layer.Tile(layerProperty);
            break;
        case "ol.layer.Vector":
            //矢量图层添加样式
            if(layerOptions.hasOwnProperty("options")
                && layerOptions["options"] != null
                && layerOptions["options"].hasOwnProperty("styleSet")
                && layerOptions["options"]["styleSet"] != null
                && layerOptions["options"]["styleSet"].hasOwnProperty("code")){
                layerProperty['style'] = eval('(' + layerOptions["options"]["styleSet"]["code"] + ')');
            }
            layer = new ol.layer.Vector(layerProperty);
            break;
        case "ol.layer.VectorTile":
            break;
        case "ol.layer.Heatmap":
            break;
    }
    if(layer != null){
        //给图层添加属性
        layer.setProperties({'layerType':layerType})
        if(layerOptions.hasOwnProperty("layerId") && layerOptions['layerId'] != null){
            layer.setProperties({'layerId':layerOptions['layerId']})
        }
        if(layerOptions.hasOwnProperty("aliasName") && layerOptions['aliasName'] != null){
            layer.setProperties({'aliasName':layerOptions['aliasName']})
        }

        //地图添加新增图层
        _this.mainMap.addLayer(layer);
        //图层设置数据源
        if(layerOptions.hasOwnProperty("source") && layerOptions['source'] != null){
            if(layerOptions['source'].hasOwnProperty('type')
                && (layerOptions['source']['type'] == 'ol.supermap.FeatureService' || layerOptions['source']['type'] == 'ol.supermap.FeatureService')){
                _this.setSource_featureService(layer,layerOptions['source']['type'],layerOptions['source']['options']);
            }else {
                layer.setSource(layerOptions.source);
            }
        }

        //矢量图层添加触发事件
        if(layerType == "ol.layer.Vector"){
            var pointerMoveStyle = null,pointerMoveCallBack = null,
                clickStyle = null,clickCallBack = null;
            _this.removeAllSelectInteraction();
            if(layerOptions.hasOwnProperty("options")
                && layerOptions["options"] != null
                && layerOptions["options"].hasOwnProperty("stylePointerMove")
                && layerOptions["options"]["stylePointerMove"] != null
                && layerOptions["options"]["stylePointerMove"].hasOwnProperty("code")){
                pointerMoveStyle = eval('(' + layerOptions["options"]["stylePointerMove"]["code"] + ')');
            }
            if(layerOptions.hasOwnProperty("options")
                && layerOptions["options"] != null
                && layerOptions["options"].hasOwnProperty("pointerMove")
                && layerOptions["options"]["pointerMove"] != null
                && layerOptions["options"]["pointerMove"].hasOwnProperty("code")){
                pointerMoveCallBack = eval('(' + layerOptions["options"]["pointerMove"]["code"] + ')');
            }
            if(layerOptions.hasOwnProperty("options")
                && layerOptions["options"] != null
                && layerOptions["options"].hasOwnProperty("styleClick")
                && layerOptions["options"]["styleClick"] != null
                && layerOptions["options"]["styleClick"].hasOwnProperty("code")){
                clickStyle = eval('(' + layerOptions["options"]["styleClick"]["code"] + ')');
            }
            if(layerOptions.hasOwnProperty("options")
                && layerOptions["options"] != null
                && layerOptions["options"].hasOwnProperty("click")
                && layerOptions["options"]["click"] != null
                && layerOptions["options"]["click"].hasOwnProperty("code")){
                clickCallBack = eval('(' + layerOptions["options"]["click"]["code"] + ')');
            }

            if(pointerMoveStyle != null || pointerMoveCallBack != null){
                _this.addInteraction(layerName,"pointerMove",pointerMoveStyle,pointerMoveCallBack);
            }
            if(clickStyle != null || clickCallBack != null){
                _this.addInteraction(layerName,"click",clickStyle,clickCallBack);
            }
        }
    }
}

C3GIS.prototype.setSourceForLayer = function (layerName,source) {
    var _this = this,layer = _this.getLayByName(layerName);
    if(layer != null){
        layer.setSource(source);
    }
}

// 给图层设置supermap或arcgis FeatureService
C3GIS.prototype.setSource_featureService = function (layer,sourceType,sourceOptions) {
    if(sourceType === 'ol.supermap.FeatureService'
        && sourceOptions.hasOwnProperty('url')
        && sourceOptions['url'] != ''
        && sourceOptions.hasOwnProperty('datasource')
        && sourceOptions['datasource'] != ''
        && sourceOptions.hasOwnProperty('dataset')
        && sourceOptions['dataset'] != ''){
        var serviceParam,
            queryParameter={name: sourceOptions['dataset'] + '@' + sourceOptions['datasource']};
        queryParameter['attributeFilter'] = sourceOptions.hasOwnProperty('attributeFilter') && sourceOptions['attributeFilter'] != ''
            ? sourceOptions['attributeFilter']:'SMID >= 0';
        if(sourceOptions.hasOwnProperty('geometry') && sourceOptions['geometry'] != ''){
            serviceParam = new SuperMap.GetFeaturesByGeometryParameters({
                datasetNames: [sourceOptions['datasource'] + ':' + sourceOptions['dataset']],
                queryParameter: queryParameter,
                geometry: (new SuperMap.Format.WKT()).read(sourceOptions['geometry']).geometry,
                spatialQueryMode: "INTERSECT"
            });
            new ol.supermap.FeatureService(sourceOptions['url']).getFeaturesByGeometry(serviceParam,function (serviceResult) {
                var vectorSource = new ol.source.Vector({
                    features: (new ol.format.GeoJSON()).readFeatures(serviceResult.result.features),
                    wrapX: false
                });
                layer.setSource(vectorSource);
            });
        }else {
            serviceParam = new SuperMap.GetFeaturesBySQLParameters({
                queryParameter: queryParameter,
                datasetNames: [sourceOptions['datasource'] + ':' + sourceOptions['dataset']]
            });
            new ol.supermap.FeatureService(sourceOptions['url']).getFeaturesBySQL(serviceParam,function (serviceResult) {
                var vectorSource = new ol.source.Vector({
                    features: (new ol.format.GeoJSON()).readFeatures(serviceResult.result.features),
                    wrapX: false
                });
                layer.setSource(vectorSource);
            });
        }
    }else if(sourceType === 'arcgis.FeatureService'){

    }
}
C3GIS.prototype.setSourceForLayer_featureService = function (layerName,sourceType,sourceOptions) {
    var _this = this,layer = _this.getLayByName(layerName);
    if(layer != null){
        _this.setSource_featureService(layer,sourceType,sourceOptions);
    }
}

C3GIS.prototype.setStyleForVectoryLayer = function (layerName,style) {
    var _this = this,layer = _this.getLayByName(layerName);
    if(layer != null){
        layer.setStyle(style);
    }
}

/**
 * 根据图层编号隐藏图层
 * @param layerId
 */
C3GIS.prototype.hideLayerById = function (layerId) {
    var _this = this,selectedLayer = _this.getLayerById(layerId);
    if(selectedLayer != null && selectedLayer.getVisible()){
        selectedLayer.setVisible(false);
    }
}

/**
 * 根据图层名称隐藏图层
 * @param layerName
 */
C3GIS.prototype.hideLayerByName = function (layerName) {
    var _this = this,selectedLayer = _this.getLayByName(layerName);
    if(selectedLayer != null && selectedLayer.getVisible()){
        selectedLayer.setVisible(false);
    }
}

/**
 * 根据图层编号显示图层
 * @param layerId
 */
C3GIS.prototype.showLayerById = function (layerId) {
    var _this = this,selectedLayer = _this.getLayerById(layerId);
    if(selectedLayer != null && !selectedLayer.getVisible()){
        selectedLayer.setVisible(true);
    }
}

/**
 * 根据图层名称显示图层
 * @param layerName
 */
C3GIS.prototype.showLayerByName = function (layerName) {
    var _this = this,selectedLayer = _this.getLayByName(layerName);
    if(selectedLayer != null && !selectedLayer.getVisible()){
        selectedLayer.setVisible(true);
    }
}

/**
 * 根据图层编号设置Zindex
 * @param layerId
 * @param zIndex
 */
C3GIS.prototype.setZIndexById = function (layerId,zIndex) {
    var _this = this,selectedLayer = _this.getLayerById(layerId);
    if(selectedLayer != null){
        selectedLayer.setZIndex(zIndex);
    }
}

/**
 * 根据图层名称设置Zindex
 * @param layerName
 * @param zIndex
 */
C3GIS.prototype.setZIndexByName = function (layerName,zIndex) {
    var _this = this,selectedLayer = _this.getLayByName(layerName);
    if(selectedLayer != null){
        selectedLayer.setZIndex(zIndex);
    }
}
/**********************************layer *****************************************/

/**********************************source start*****************************************/

C3GIS.prototype.createSourceByType = function (sourceType,sourceOption) {
    var source = null;
    if(sourceType == null || sourceType == "") return source;
    switch(sourceType){
        case "ol.source.WMTS":
            var projection = ol.proj.get(sourceOption.hasOwnProperty("projection")?sourceOption.projection:"EPSG:4326"),
                projectionExtent = projection.getExtent(),
                size = ol.extent.getWidth(projectionExtent)/256,
                resolutions = new Array(20),
                matrixIds = new Array(14);
            for(var z = 0;z < 20;z++){
                resolutions[z] = size/Math.pow(2,z);
                matrixIds[z] = z;
            }
            source = new ol.source.WMTS({
                url:sourceOption.url,
                layer:sourceOption.layer,
                format:sourceOption.format,
                tileGrid:new ol.tilegrid.WMTS({
                    origin: ol.extent.getTopLeft(projectionExtent),
                    resolutions: resolutions,
                    matrixIds: matrixIds
                }),
                matrixSet:sourceOption.matrixSet,
                style: sourceOption.style
            });
            break;
        case "ol.source.TileArcGISRest":
            source = new ol.source.TileArcGISRest({
                url:sourceOption.url
            });
            break;
        case "ol.source.TileSuperMapRest":
            source = new ol.source.TileSuperMapRest({
                url:sourceOption.url
            });
            break;
        case "ol.source.Vector":
            var vectorPrototype = {};
            if(sourceOption.hasOwnProperty("url") && sourceOption.url != null){
                var sourceUrl = sourceOption.url;
                if(sourceUrl.indexOf('?') > 0){
                    if(sourceUrl.indexOf('http') == 0){
                        sourceUrl += '&date=' + (new Date()).valueOf();
                    }else {
                        sourceUrl += '&key=3c4c1fe05b125209f9a50f00708097fbf73ba920449bde6f051a0d66f2f6997b&date=' + (new Date()).valueOf();
                    }

                }else {
                    if(sourceUrl.indexOf('http') == 0){
                        sourceUrl += '?date=' + (new Date()).valueOf();
                    }else {
                        sourceUrl += '?key=3c4c1fe05b125209f9a50f00708097fbf73ba920449bde6f051a0d66f2f6997b&date=' + (new Date()).valueOf();
                    }
                }
                $.ajax({
                    type: 'get',
                    url: sourceUrl,
                    dataType: 'json',
                    async: false,
                    success: function(data) {
                        if(data == null) return;
                        var featureArray = (new ol.format.GeoJSON()).readFeatures(data),
                            attr,
                            attrArray = [];
                        if(featureArray.length > 0){
                            for(var i = 0,len = featureArray.length;i < len;i++){
                                attr = featureArray[i].getProperties();
                                if(attr.hasOwnProperty('geometry')){
                                    delete attr.geometry;
                                }
                                attrArray.push(attr);
                            }
                        }
                        source = new ol.source.Vector({
                            features: featureArray
                        });
                        if(sourceOption.hasOwnProperty("successCallBack")){
                            sourceOption.successCallBack(attrArray);
                        }
                    },
                    error:function (error) {
                        if(sourceOption.hasOwnProperty("errorCallBack")){
                            sourceOption.errorCallBack(error);
                        }
                    }
                });


            }else if(sourceOption.hasOwnProperty("features")
                && Object.prototype.toString.call(sourceOption.features) == "[object Array]"){
                source = new ol.source.Vector({
                    features: sourceOption.features
                });
                if(sourceOption.hasOwnProperty("successCallBack")){
                    eval("("+ sourceOption.successCallBack +")")
                }
            }
            break;
    }
    return source;
}

/**********************************source start*****************************************/





/**********************************overlay start*****************************************/
/**
 * 生成并显示浮动窗
 * @param popupOptions，参数对象属性如下：
 * themesClass：主题类，主类名和主题类名，枚举：black/gray
 * toolArray：按钮属性数组，属性如下：id（按钮<a>标签的id）、onclick（单击回调函数）、src（按钮图标地址）、text（按钮文字）
 * height：浮动窗高度
 * width：浮动窗宽度
 * url：浮动窗内嵌网页地址
 * coordinate：浮动窗位置，形如[120, 38]
 */
C3GIS.prototype.createPopup = function (popupOptions) {
    var _this = this;
    //浮动窗头部——关闭按钮
    var themesClass = popupOptions.hasOwnProperty("themesClass")
        && popupOptions["themesClass"] != null
        && popupOptions["themesClass"] != ""
            ? popupOptions["themesClass"] : "black",
        popupHeader = "<a href='' id='popup-closer' class='ol-popup-closer ol-popup-closer_";
    popupHeader += themesClass;
    popupHeader += "'></a>";

    //浮动窗头部——功能按钮
    popupHeader += "<div class='pop_title pop_title_" + themesClass;
    popupHeader += "'><div class='title_left title_left_" + themesClass;
    popupHeader += "'>"
    if(popupOptions.hasOwnProperty("toolArray")
        && popupOptions["toolArray"] != null
        && popupOptions["toolArray"].length > 0){
        popupHeader += "<ul>";
        for(var i = 0,len = popupOptions["toolArray"].length;i < len;i++){
            popupHeader += "<li><a href='#' id='"
                + popupOptions["toolArray"][i]["id"]
                + "' onclick='" + popupOptions["toolArray"][i]["onclick"]
                + "'><img src='" + popupOptions["toolArray"][i]["src"] + "'" + " width='16px' height='16px'>"
                + popupOptions["toolArray"][i]["text"] + "</a></li>";
        }
        popupHeader += "</ul>";
    }
    popupHeader += "</div></div>";

    var popupContent = "<div id='popup-content'>";
    popupContent += "<iframe id='myiframe' class='myiframe' name='myiframe' style='width:100%;overflow:-Scroll;overflow-x:hidden' marginwidth='0' marginheight='0' height='";
    popupContent += popupOptions['height'] + "px' hspace='0' vspace='0' frameborder='0' allowtransparency='true' src='";
    popupContent += popupOptions['url'] + "'></iframe>"

    //_this.reinitIframe('myiframe',popupOptions['height']);
    // window.setTimeout("gis.reinitIframe('myiframe'," + popupOptions['height'] + ")", 200);
    popupContent += "</div>";

    var popupDiv = document.getElementById("popup");

    popupDiv.innerHTML = popupHeader + popupContent;
    popupDiv.style.setProperty("min-width",popupOptions["width"] + "px");
    _this.popupOverlay.setElement(popupDiv);
    _this.popupOverlay.setPosition(popupOptions['coordinate']);

    popupDiv.setAttribute("class", "ol-popup ol-popup_" + themesClass);

    document.getElementById('popup-closer').onclick = function () {
        _this.popupOverlay.setPosition(undefined);
        this.blur();
        return false;
    };
}
C3GIS.prototype.reinitIframe = function (iframeId, maxheight) {
    var iframe = document.getElementById(iframeId);
    try {
        var iframeWin = iframe.contentWindow || iframe.contentDocument.parentWindow;
        if (iframeWin.document.body) {
            var scrollHeight = iframeWin.document.documentElement.scrollHeight || iframeWin.document.body.scrollHeight;
            if((maxheight == '' || maxheight == 0) && scrollHeight > 400)
                scrollHeight = 400;
            else if(maxheight != '' && maxheight != 0 && scrollHeight > maxheight)
                scrollHeight = maxheight;
            iframe.height = scrollHeight + 20;
        }
        $(iframe).contents().find("body").css({'overflow': '-Scroll', 'overflow-x': 'hidden'});//去除横向滚动条，存在跨域问题，需部署在服务器上测试
    } catch (ex) {
        console.log('reinitIframe error:' + ex);
    }
}
/**********************************overlay start*****************************************/


